<?PHP
namespace SDF\Lib\Helpers;

/**
 * 表单工具类
 * @package SDF\Lib\Helpers
 */
class Form {

    /**
     * 开始一个表单的输出
     * @param string $action
     * @param string $attributes
     * @param array $hidden
     * @return string
     */
    public static function form_open($action = '', $attributes = '', $hidden = array()){
        if ($attributes == '') {
            $attributes = 'method="post"';
        }
        $form = '<form action="' . $action . '"';
        $form .= self::_attributes_to_string($attributes, TRUE);
        $form .= '>';
        if (is_array($hidden) AND count($hidden) > 0) {
            $form .= sprintf("<div style=\"display:none\">%s</div>", self::form_hidden($hidden));
        }
        return $form;
    }

    /**
     * 隐藏域
     * @param $name
     * @param string $value
     * @param bool $recursing
     * @return string
     */
    public static function form_hidden($name, $value = '', $recursing = FALSE) {
        static $form;
        if ($recursing === FALSE) {
            $form = "\n";
        }
        if (is_array($name)) {
            foreach ($name as $key => $val) {
                self::form_hidden($key, $val, TRUE);
            }
            return $form;
        }
        if (!is_array($value)) {
            $form .= '<input type="hidden" name="' . $name . '" value="' . self::form_prep($value, $name) . '" />' . "\n";
        } else {
            foreach ($value as $k => $v) {
                $k = (is_int($k)) ? '' : $k;
                self::form_hidden($name . '[' . $k . ']', $v, TRUE);
            }
        }
        return $form;
    }

    /**
     * input
     * @param string $data
     * @param string $value
     * @param string $extra
     * @return string
     */
    public static function form_input($data = '', $value = '', $extra = '') {
        $defaults = array('type' => 'text', 'name' => ((!is_array($data)) ? $data : ''), 'value' => $value);

        return "<input " . self::_parse_form_attributes($data, $defaults) . $extra . " />";
    }

    /**
     * 密码input
     * @param string $data
     * @param string $value
     * @param string $extra
     * @return string
     */
    public static function form_password($data = '', $value = '', $extra = '') {
        if (!is_array($data)) {
            $data = array('name' => $data);
        }

        $data['type'] = 'password';
        return self::form_input($data, $value, $extra);
    }

    /**
     * @param string $data
     * @param string $value
     * @param string $extra
     * @return mixed
     */
    public static function form_upload($data = '', $value = '', $extra = '') {
        if (!is_array($data)) {
            $data = array('name' => $data);
        }

        $data['type'] = 'file';
        return self::form_input($data, $value, $extra);
    }

    /**
     * 多行文本域
     * @param string $data
     * @param string $value
     * @param string $extra
     * @return string
     */
    public static function form_textarea($data = '', $value = '', $extra = '') {
        $defaults = array('name' => ((!is_array($data)) ? $data : ''), 'cols' => '40', 'rows' => '10');

        if (!is_array($data) OR !isset($data['value'])) {
            $val = $value;
        } else {
            $val = $data['value'];
            unset($data['value']); // textareas don't use the value attribute
        }

        $name = (is_array($data)) ? $data['name'] : $data;
        return "<textarea " . self::_parse_form_attributes($data, $defaults) . $extra . ">" . self::form_prep($val, $name) . "</textarea>";
    }

    /**
     * 多选框
     * @param string $name
     * @param array $options
     * @param array $selected
     * @param string $extra
     * @return mixed
     */
    public static function form_multiselect($name = '', $options = array(), $selected = array(), $extra = '') {
        if (!strpos($extra, 'multiple')) {
            $extra .= ' multiple="multiple"';
        }

        return self::form_dropdown($name, $options, $selected, $extra);
    }

    /**
     * 下拉选择框
     * @param string $name
     * @param array $options
     * @param array $selected
     * @param string $extra
     * @return string
     */
    public static function form_dropdown($name = '', $options = array(), $selected = array(), $extra = '') {
        if (!is_array($selected)) {
            $selected = array($selected);
        }
        // If no selected state was submitted we will attempt to set it automatically
        if (count($selected) === 0) {
            // If the form name appears in the $_POST array we have a winner!
            if (isset($_POST[$name])) {
                $selected = array($_POST[$name]);
            }
        }

        if ($extra != '') $extra = ' ' . $extra;
        $multiple = (count($selected) > 1 && strpos($extra, 'multiple') === FALSE) ? ' multiple="multiple"' : '';
        $form = '<select name="' . $name . '"' . $extra . $multiple . ">\n";
        if (!empty($options)) foreach ($options as $key => $val) {
            $key = (string)$key;

            if (is_array($val) && !empty($val)) {
                $form .= '<optgroup label="' . $key . '">' . "\n";

                foreach ($val as $optgroup_key => $optgroup_val) {
                    $sel = (in_array($optgroup_key, $selected)) ? ' selected="selected"' : '';
                    $form .= '<option value="' . $optgroup_key . '"' . $sel . '>' . (string)$optgroup_val . "</option>\n";
                }

                $form .= '</optgroup>' . "\n";
            } else {
                $sel = (in_array($key, $selected)) ? ' selected="selected"' : '';

                $form .= '<option value="' . $key . '"' . $sel . '>' . (string)$val . "</option>\n";
            }
        }

        $form .= '</select>';

        return $form;
    }

    /**
     * 多选框
     * @param string $data
     * @param string $value
     * @param bool $checked
     * @param string $extra
     * @return string
     */
    public static function form_checkbox($data = '', $value = '', $checked = FALSE, $extra = '') {
        $defaults = array('type' => 'checkbox', 'name' => ((!is_array($data)) ? $data : ''), 'value' => $value);

        if (is_array($data) AND array_key_exists('checked', $data)) {
            $checked = $data['checked'];

            if ($checked == FALSE) {
                unset($data['checked']);
            } else {
                $data['checked'] = 'checked';
            }
        }

        if ($checked == TRUE) {
            $defaults['checked'] = 'checked';
        } else {
            unset($defaults['checked']);
        }

        return "<input " . self::_parse_form_attributes($data, $defaults) . $extra . " />";
    }

    /**
     * 单选
     * @param string $data
     * @param string $value
     * @param bool $checked
     * @param string $extra
     * @return string
     */
    public static function form_radio($data = '', $value = '', $checked = FALSE, $extra = '') {
        if (!is_array($data)) {
            $data = array('name' => $data);
        }

        $data['type'] = 'radio';
        return self::form_checkbox($data, $value, $checked, $extra);
    }

    /**
     * 提交按钮
     * @param string $data
     * @param string $value
     * @param string $extra
     * @return string
     */
    public static function form_submit($data = '', $value = '', $extra = '') {
        $defaults = array('type' => 'submit', 'name' => ((!is_array($data)) ? $data : ''), 'value' => $value);
        return "<input " . self::_parse_form_attributes($data, $defaults) . $extra . " />";
    }

    /**
     * 重置
     * @param string $data
     * @param string $value
     * @param string $extra
     * @return string
     */
    public static function form_reset($data = '', $value = '', $extra = '') {
        $defaults = array('type' => 'reset', 'name' => ((!is_array($data)) ? $data : ''), 'value' => $value);

        return "<input " . self::_parse_form_attributes($data, $defaults) . $extra . " />";
    }

    /**
     * 按钮
     * @param string $data
     * @param string $content
     * @param string $extra
     * @return string
     */
    public static function form_button($data = '', $content = '', $extra = '') {
        $defaults = array('name' => ((!is_array($data)) ? $data : ''), 'type' => 'button');
        if (is_array($data) AND isset($data['content'])) {
            $content = $data['content'];
            unset($data['content']); // content is not an attribute
        }
        return "<button " . self::_parse_form_attributes($data, $defaults) . $extra . ">" . $content . "</button>";
    }

    /**
     * label
     * @param string $label_text
     * @param string $id
     * @param array $attributes
     * @return string
     */
    public static function form_label($label_text = '', $id = '', $attributes = array()) {
        $label = '<label';
        if ($id != '') {
            $label .= " for=\"$id\"";
        }
        if (is_array($attributes) AND count($attributes) > 0) {
            foreach ($attributes as $key => $val) {
                $label .= ' ' . $key . '="' . $val . '"';
            }
        }
        $label .= ">$label_text</label>";
        return $label;
    }

    /**
     * 分组开始
     * @param string $legend_text
     * @param array $attributes
     * @return string
     */
    public static function form_fieldset($legend_text = '', $attributes = array()) {
        $fieldset = "<fieldset";
        $fieldset .= self::_attributes_to_string($attributes, FALSE);
        $fieldset .= ">\n";
        if ($legend_text != '') {
            $fieldset .= "<legend>$legend_text</legend>\n";
        }
        return $fieldset;
    }

    /**
     * 分组结束
     * @param string $extra
     * @return string
     */
    public static function form_fieldset_close($extra = '') {
        return "</fieldset>" . $extra;
    }

    /**
     * @param string $extra
     * @return string
     */
    public static function form_close($extra = '') {
        return "</form>" . $extra;
    }

    /**
     * 格式处理表单值，避免HTML识别错误
     * @param string $str
     * @param string $field_name
     * @return array|mixed|string
     */
    public static function form_prep($str = '', $field_name = '') {
        static $prepped_fields = array();
        // if the field name is an array we do this recursively
        if (is_array($str)) {
            foreach ($str as $key => $val) {
                $str[$key] = self::form_prep($val);
            }
            return $str;
        }
        if ($str === '') {
            return '';
        }
        if (isset($prepped_fields[$field_name])) {
            return $str;
        }
        $str = htmlspecialchars($str);
        // In case htmlspecialchars misses these.
        $str = str_replace(array("'", '"'), array("&#39;", "&quot;"), $str);
        if ($field_name != '') {
            $prepped_fields[$field_name] = $field_name;
        }
        return $str;
    }

    /**
     * 校验表单值
     * @param string $field
     * @param string $default
     * @return array|mixed|string
     */
    public static function set_value($field = '', $default = '') {
        if (FALSE === ($OBJ = &self::_get_validation_object()())) {
            if (!isset($_POST[$field])) {
                return $default;
            }
            return self::form_prep($_POST[$field], $field);
        }
        return self::form_prep($OBJ->set_value($field, $default), $field);
    }

    /**
     * 设置选中项
     * @param string $field
     * @param string $value
     * @param bool $default
     * @return string
     */
    public static function set_select($field = '', $value = '', $default = FALSE){
        $OBJ = & self::_get_validation_object();
        if ($OBJ === FALSE) {
            if (!isset($_POST[$field])) {
                if (count($_POST) === 0 AND $default == TRUE) {
                    return ' selected="selected"';
                }
                return '';
            }
            $field = $_POST[$field];
            if (is_array($field)) {
                if (!in_array($value, $field)) {
                    return '';
                }
            } else {
                if (($field == '' OR $value == '') OR ($field != $value)) {
                    return '';
                }
            }
            return ' selected="selected"';
        }
        return $OBJ->set_select($field, $value, $default);
    }

    /**
     * 设置checkbox是否被选择
     * @param string $field
     * @param string $value
     * @param bool $default
     * @return string
     */
    public static function set_checkbox($field = '', $value = '', $default = FALSE) {
        $OBJ =& self::_get_validation_object();
        if ($OBJ === FALSE) {
            if (!isset($_POST[$field])) {
                if (count($_POST) === 0 AND $default == TRUE) {
                    return ' checked="checked"';
                }
                return '';
            }
            $field = $_POST[$field];
            if (is_array($field)) {
                if (!in_array($value, $field)) {
                    return '';
                }
            } else {
                if (($field == '' OR $value == '') OR ($field != $value)) {
                    return '';
                }
            }
            return ' checked="checked"';
        }
        return $OBJ->set_checkbox($field, $value, $default);
    }

    /**
     * 设置radio是否被选中
     * @param string $field
     * @param string $value
     * @param bool $default
     * @return string
     */
    public static function set_radio($field = '', $value = '', $default = FALSE) {
        $OBJ = & self::_get_validation_object();
        if ($OBJ === FALSE) {
            if (!isset($_POST[$field])) {
                if (count($_POST) === 0 AND $default == TRUE) {
                    return ' checked="checked"';
                }
                return '';
            }
            $field = $_POST[$field];
            if (is_array($field)) {
                if (!in_array($value, $field)) {
                    return '';
                }
            } else {
                if (($field == '' OR $value == '') OR ($field != $value)) {
                    return '';
                }
            }
            return ' checked="checked"';
        }
        return $OBJ->set_radio($field, $value, $default);
    }

    /**
     * 输出错误表单信息
     * @param string $field
     * @param string $prefix
     * @param string $suffix
     * @return string
     */
    public static function form_error($field = '', $prefix = '', $suffix = '') {
        if (FALSE === ($OBJ =& self::_get_validation_object())) {
            return '';
        }
        return $OBJ->error($field, $prefix, $suffix);
    }

    /**
     * 返回表单校验错误
     * @param string $prefix
     * @param string $suffix
     * @return string
     */
    public static function validation_errors($prefix = '', $suffix = '') {
        if (FALSE === ($OBJ = & self::_get_validation_object())) {
            return '';
        }
        return $OBJ->error_string($prefix, $suffix);
    }

    /**
     * xxx
     * @param $attributes
     * @param $default
     * @return string
     */
    public static function _parse_form_attributes($attributes, $default) {
        if (is_array($attributes)) {
            foreach ($default as $key => $val) {
                if (isset($attributes[$key])) {
                    $default[$key] = $attributes[$key];
                    unset($attributes[$key]);
                }
            }
            if (count($attributes) > 0) {
                $default = array_merge($default, $attributes);
            }
        }
        $att = '';
        foreach ($default as $key => $val) {
            if ($key == 'value') {
                $val = self::form_prep($val, $default['name']);
            }
            $att .= $key . '="' . $val . '" ';
        }
        return $att;
    }

    /**
     * 属性数组格式化未HTML字符串
     * @param $attributes
     * @param bool $formtag
     * @return string
     */
    public static function _attributes_to_string($attributes, $formtag = FALSE) {
        $atts = '';
        if (is_string($attributes) AND strlen($attributes) > 0) {
            if ($formtag == TRUE AND strpos($attributes, 'method=') === FALSE) {
                $attributes .= ' method="post"';
            }
            /*if ($formtag == TRUE AND strpos($attributes, 'accept-charset=') === FALSE) {
                $attributes .= ' accept-charset="' . strtolower(config_item('charset')) . '"';
            }*/
            return ' '.$attributes;
        }
        if (is_object($attributes) AND count($attributes) > 0) {
            $attributes = (array)$attributes;
        }
        if (is_array($attributes) AND count($attributes) > 0) {
            if (!isset($attributes['method']) AND $formtag === TRUE) {
                $atts .= ' method="post"';
            }
            /*if (!isset($attributes['accept-charset']) AND $formtag === TRUE) {
                $atts .= ' accept-charset="' . strtolower(config_item('charset')) . '"';
            }*/
            foreach ($attributes as $key => $val) {
                $atts .= ' ' . $key . '="' . $val . '"';
            }
        }
        return $atts;
    }

    /**
     * 获取表单验证类
     * @return bool
     */
    public static function &_get_validation_object() {
        $return = FALSE;
        /*if (FALSE !== ($object = $CI->load->is_loaded('form_validation'))) {
            if (!isset($CI->$object) OR !is_object($CI->$object)) {
                return $return;
            }
            return $CI->$object;
        }*/
        return $return;
    }


}